import json
import os
import queue
import ssl
import threading
import time
import uuid

import pygame
import requests

import config
import credentials


class Reader(object):
    def __init__(self, book, content):
        self.lines_len = 0
        self.content = content
        self.book = book
        with open('progress.json', 'r+') as f:
            content = f.read()
            content = json.loads(content)
            self.content.update(content)
            self.progress = self.content[self.book]

    def get_info(self, ctx):
        if ctx == 'token':
            # 读取token
            with open('token', 'r') as f:
                token = f.read()
            # 超时重新获取token
            if not token:
                token = self._get_token()
            return token
        elif ctx == 'mac':
            # 获取本机mac
            mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
            return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])

    def _get_token(self):
        # 访问https
        ssl._create_default_https_context = ssl._create_unverified_context
        data = dict()
        data['grant_type'] = 'client_credentials'
        data['client_id'] = credentials.APIKEY
        data['client_secret'] = credentials.Secret_Key
        url = config.URL.tokenurl
        token = requests.post(url=url, data=data, verify=True)
        token = token.json()['access_token']
        with open('token', 'w') as f:
            f.write(token)
        return token

    # 获取文本
    # 文本生产者
    def get_text(self, text, book):
        book = config.bookdir + book
        with open(book, 'r', encoding='gbk', errors='ignore') as f:
            lines = f.readlines()
            self.lines_len = len(lines)
            for line in range(self.progress-1, self.lines_len):
                time.sleep(2)
                text.put(lines[line].encode('utf-8'))
        text.join()
        # text = '发音人选择即使在下载该网页后断开了因特网连接，该页面的所有数据仍然会在你的计算机中'

    def sender_son_req(self, url, data):
        while 1:
            # time.sleep(2)
            try:
                ssl._create_default_https_context = ssl._create_unverified_context
                res = requests.post(url=url, data=data, verify=True)
                if res.status_code == 200:
                    return res
            except Exception as e:
                # print('sender_son_req: ', e)
                continue

    def sender_son_write(self, m, res):
        # 转成文本
        m += 1
        while 1:
            time.sleep(2)
            try:
                with open('%sRomeoAndJuliet%s.mp3' % (config.audiocache, m), 'wb') as cachefile:
                    for chunk in res.iter_content():
                        cachefile.write(chunk)
                return m
            except Exception as e:
                # print('sender_son_write: ', e)
                continue

    # 文本消费者
    # 音频生产者
    def sender(self, text, audio):
        m = 0
        while 1:
            data = dict()
            data['tex'] = text.get()
            data['tok'] = self.get_info('token')
            data['cuid'] = self.get_info('mac')
            data['ctp'] = 1
            data['lan'] = 'zh'
            data['spd'] = config.speed
            data['per'] = config.per
            data['vol'] = config.vol
            data['pit'] = config.pit
            data['aue'] = config.aue
            url = config.URL.url
            res = self.sender_son_req(url, data)
            m = self.sender_son_write(m, res)
            audio.put('RomeoAndJuliet%s.mp3' % m)
            if m == 100:
                m = 1

    # 输出语音
    def player(self, target):
        while 1:
            time.sleep(0.5)
            try:
                pygame.mixer.music.load(target)
                pygame.mixer.music.play()
                return
            except Exception as e:
                print('player:', e)
                # 此时怀疑token错误, 删除旧的token
                with open('token', 'w') as f:
                    f.write('')
                continue

    # 音频消费者
    def play(self, audio):
        pygame.mixer.init()
        while 1:
            if not pygame.mixer.music.get_busy():
                target = audio.get()
                target = config.audiocache + target
                self.player(target)
                self.update_progress()

    def update_progress(self):
        with open('progress.json', 'w+') as f:
            pro = self.progress/self.lines_len*100
            print(f'当前正在读第{self.progress}行, '
                  f'进度{format(pro, "0.2f")}%')
            self.progress += 1
            self.content[self.book] = self.progress
            f.write(json.dumps(self.content))


def books():
    dirs = os.listdir(config.bookdir)
    booklist = []
    n = 0
    for dir in dirs:
        if os.path.isdir(config.bookdir+dir):
            print('【%02s】: %s' % (n+1, dir))
            n += 1
    selected_colume = input('请输入分类编号: ')
    dir = dirs[int(selected_colume)-1]
    items = os.listdir(config.bookdir+dir)
    n = 0
    for name in items:
        if name.endswith(".txt"):
            booklist.append(dir+'/'+name)
            print('【%02s】: %s' % (n+1, name))
            n += 1
    selected_book = input('请输入书名编号: ')
    selected_book = booklist[int(selected_book)-1]
    content = {key: 0 for key in booklist}
    return selected_book, content


def main():

    book, content = books()
    shaniu = Reader(book, content)
    text = queue.Queue()
    audio = queue.Queue()
    # 欢迎语来一段~
    text.put(config.welcome)
    print(config.welcome)
    tp = threading.Thread(target=shaniu.get_text, args=(text, book))
    tcap = threading.Thread(target=shaniu.sender, args=(text, audio))
    ac = threading.Thread(target=shaniu.play, args=(audio,))

    tp.start()
    tcap.start()
    ac.start()


if __name__ == '__main__':
    main()
